package morenoapp.model;

import com.jgoodies.binding.beans.Model;
import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import morenoapp.model.data.MorenoModelBatchJob;
import morenoapp.model.data.MorenoQuestionFace;
import morenoapp.model.data.MorenoRespondentFace;
import morenoapp.model.enums.MorenoRespondentsSortOrder;
import morenoapp.model.impl.MorenoModelImpl;
import morenoapp.model.impl.listeners.MorenoModelFire;
import morenoapp.model.listeners.MorenoModelListener;
import morenoapp.model.view2.MorenoView2Face;
import morenoapp.util.I18N;

/**
 *
 * @author dmitry.mamonov
 */
abstract class MorenoModelAbstractWrapper extends Model {
    protected MorenoModelImpl model = null;
    private MorenoView2Wrapper viewWrapper = new MorenoView2Wrapper();
    private Set<MorenoModelListener> listeners = new HashSet<MorenoModelListener>();
    private MorenoModelFire fireDelegate = new MorenoModelFire() {
        @Override
        public void fireRespondentChanged(MorenoRespondentFace respondent) {
            MorenoModelAbstractWrapper.this.fireRespondentChanged(respondent);
        }

        @Override
        public void fireQuestionChanged(MorenoQuestionFace question) {
            MorenoModelAbstractWrapper.this.fireQuestionChanged(question);
        }
    };

    protected final void loadModelImpl(File source) throws MorenoModelException {
        MorenoModelImpl backup = model;
        model = new MorenoModelImpl(fireDelegate);
        try {
            model.loadModel(source);
            viewWrapper.setDelegate(model.getViewsList());
            fireWholeModelChanged();
        } catch (MorenoModelException ex) {
            model = backup;
            throw ex;
        }
    }

    protected final void closeModelImpl() {
        model = null;
        viewWrapper.setDelegate(null);
        fireWholeModelChanged();
    }

    protected final void createModelImpl() {
        if (model!=null){
            throw new IllegalStateException(I18N.get("error.model_already_exists"));
        } else {
            model = new MorenoModelImpl(fireDelegate);
            viewWrapper.setDelegate(model.getViewsList());
            fireWholeModelChanged();
        }
    }

    protected MorenoView2Face getViewImpl() {
        return viewWrapper;
    }

    protected final void doBatchJobImpl(MorenoModelBatchJob _batchJob) {
        checkModelExists();
        if (_batchJob != null) {
            model.doBatchJob(_batchJob);
            fireWholeModelChanged();
        }
    }

    protected final MorenoQuestionFace createQuestionImpl() {
        MorenoQuestionFace result = model.createQuestion();
        fireQuestionsListChanged();
        return result;
    }

    protected final MorenoRespondentFace createRespondentImpl() {
        MorenoRespondentFace result = model.createRespondent();
        fireRespondentsListChanged();
        return result;
    }

    protected final boolean moveQuestionUpImpl(MorenoQuestionFace _question) {
        boolean result = model.moveQuestionUp(_question);
        if (result) {
            fireQuestionsListChanged();
        }
        return result;
    }

    protected final boolean moveQuestionDownImpl(MorenoQuestionFace _question) {
        boolean result = model.moveQuestionDown(_question);
        if (result) {
            fireQuestionsListChanged();
        }
        return result;
    }

    protected final void deleteQuestionsImpl(Collection _questions) {
        model.deleteQuestions(_questions);
        fireQuestionsListChanged();
        fireRespondentsListChanged();
    }

    protected final void deleteRespondentsImpl(Collection _respondents) {
        model.deleteRespondents(_respondents);
        fireRespondentsListChanged();
    }

    protected final void sortRespondentsImpl(MorenoRespondentsSortOrder _order) {
        model.sortRespondents(_order);
        fireRespondentsListChanged();
    }

    protected final void addModelListenerImpl(MorenoModelListener _value) {
        listeners.add(_value);
    }

    protected final void removeModelListenerImpl(MorenoModelListener _value) {
        listeners.remove(_value);
    }

    protected void fireRespondentChanged(MorenoRespondentFace changed) {
        for (MorenoModelListener lst : new ArrayList<MorenoModelListener>(listeners)) {
            lst.onRespondentChanged(changed);
            lst.onAnyElementChanged();
        }
    }

    protected void fireRespondentsListChanged() {
        for (MorenoModelListener lst : new ArrayList<MorenoModelListener>(listeners)) {
            lst.onRespondentsListChanged();
            lst.onAnyElementChanged();
        }
    }

    protected void fireQuestionsListChanged() {
        for (MorenoModelListener lst : new ArrayList<MorenoModelListener>(listeners)) {
            lst.onQuestionsListChanged();
            lst.onAnyElementChanged();
        }
    }

    protected void fireQuestionChanged(MorenoQuestionFace queston) {
        for (MorenoModelListener lst : new ArrayList<MorenoModelListener>(listeners)) {
            lst.onQuestionChanged(queston);
            lst.onAnyElementChanged();
        }
    }

    protected void fireQuestionItemsCountChanged() {
        for (MorenoModelListener lst : new ArrayList<MorenoModelListener>(listeners)) {
            lst.onQuestionItemsCountChanged();
            lst.onAnyElementChanged();
        }
    }

    protected void fireWholeModelChanged() {
        for (MorenoModelListener lst : new ArrayList<MorenoModelListener>(listeners)) {
            lst.onRespondentsListChanged();
            lst.onQuestionsListChanged();
            lst.onQuestionItemsCountChanged();
            lst.onWholeModelChanged();
            lst.onAnyElementChanged();
        }
        firePropertiesAllChanged();
    }

    protected abstract void firePropertiesAllChanged();

    protected void checkModelExists() {
        if (model == null) {
            throw new IllegalStateException("It is no model to work with");
        }
    }

}
